package gui.buttons 
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.Dictionary;
	/**
	 * ...
	 * @author Dmitriy Gaiduk
	 */
	
	 /**
	  * When state change. example: selected changed
	  */
	 [Event(name="change",type="flash.events.Event")]
	public class BaseButton extends Sprite
	{
		protected var _button:SimpleButton;
		protected var _width:Number = 0;
		protected var _height:Number = 0;
		protected var _isInvalidation:Boolean = false;
		
		protected var _styles:Dictionary;
		
		public static const UP_SKIN:String = "UP_SKIN";
		public static const OVER_SKIN:String = "OVER_SKIN";
		public static const DOWN_SKIN:String = "DOWN_SKIN";
		
		public static const SELECTED_UP_SKIN:String = "SELECTED_UP_SKIN";
		public static const SELECTED_OVER_SKIN:String = "SELECTED_OVER_SKIN";
		public static const SELECTED_DOWN_SKIN:String = "SELECTED_DOWN_SKIN";
		
		public static const HIT_AREA:String = "HIT_AREA";
		
		
		protected var _toggle:Boolean = false;
		protected var _selected:Boolean = false;
		
		private var _buttonSelected:SimpleButton;
		private var _buttonUp:SimpleButton;
		
		public function BaseButton(parent:DisplayObjectContainer = null, 
										xpos:Number = 0, ypos:Number =  0) 
		{
			move(xpos, ypos);
			
			_width = 100;
			_height = 20;
			
			initComponent();
			
			if(parent != null)
			{
				parent.addChild(this);
			}
		}
		
		private function initComponent():void
		{
			_styles = new Dictionary();
			_button = new SimpleButton();
			addChild(_button);
			_button.useHandCursor = true;
			_button.enabled = true;
			setupDefaulStyle();
			onComponentInit();
			invalidate();
		}
		
		protected function onComponentInit():void 
		{
			
		}
		
		protected function setupDefaulStyle():void 
		{
			var skinSprite:Sprite;
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics, 0xCCCCCC);
			setStyle(UP_SKIN, skinSprite);
			
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics, 0x999999);
			setStyle(OVER_SKIN, skinSprite);
			
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics, 0x666666);
			setStyle(DOWN_SKIN, skinSprite);
			
			
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics, 0x0099FF);
			setStyle(SELECTED_UP_SKIN, skinSprite);
			
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics,  0x0066FF);
			setStyle(SELECTED_OVER_SKIN, skinSprite);
			
			skinSprite = new Sprite();
			drawRect(skinSprite.graphics,  0x0033FF);
			setStyle(SELECTED_DOWN_SKIN, skinSprite);
			
		}
		
		private function drawRect(gr:Graphics, color:uint = 0xCCCCCC):void
		{
			gr.beginFill(color, 1);
			gr.drawRect(0, 0, 120, 20);
			gr.endFill();
		}
		
		public function invalidate():void
		{
			if (!_isInvalidation)
			{
				_isInvalidation = true;
				addEventListener(Event.ENTER_FRAME, onInvalidate);
			}
		}
		
		public function validateNow():void
		{
			onInvalidate(null);
		}
		
		protected function onInvalidate(e:Event):void 
		{
			removeEventListener(Event.ENTER_FRAME, onInvalidate);
			_isInvalidation = false;
			setupButtonSkin();
			//setupSkinSizes();
			setupHitArea();
		}
		
		
		protected function setupSkinSizes():void 
		{
			if ((_button == _buttonSelected) || (_button == _buttonUp))
			{
				return;
			}
			if (_button != null)
			{
				if (_button.upState != null)
				{
					_button.upState.width = width;
					_button.upState.height = height;
				}
				
				if (_button.overState != null)
				{
					_button.overState.width = width;
					_button.overState.height = height;				
				}
				
				if (_button.downState != null)
				{
					_button.downState.width = width;
					_button.downState.height = height;
				}
				
			}
		}
		
		public function move(xpos:Number, ypos:Number):void
		{
			x =	xpos;
			y = ypos;
		}
		
		override public function get width():Number 
		{
			return _width;
		}
		
		override public function set width(value:Number):void 
		{
			_width = value;
			invalidate();
		}
		
		override public function get height():Number 
		{
			return _height;
		}
		
		override public function set height(value:Number):void 
		{
			_height = value;
			invalidate();
		}
		
		public function get toggle():Boolean 
		{
			return _toggle;
		}
		
		public function set toggle(value:Boolean):void 
		{
			if (_toggle != value)
			{
				_toggle = value;
				if (!_toggle)
				{
					_selected = false;
					validateNow();
				}
			}
		}
		
		public function get selected():Boolean 
		{
			return _selected;
		}
		
		public function set selected(value:Boolean):void 
		{
			if (_selected != value)
			{
				_selected = value;
				if (toggle)
				{
					dispatchEvent(new Event(Event.CHANGE));
					validateNow();
				}
			}
		}
		
		private function setButton(btn:SimpleButton):void
		{
			if ((btn == _button) || (btn == null))
			{
				return;
			}
			
			if (btn != null)
			{
				if (btn.parent != null)
				{
					btn.parent.removeChild(btn);
				}
			}
			
			if (_button != null)
			{
				if (_button.parent != null)
				{
					_button.parent.removeChild(_button);
				}
			}
			
			_button = btn;
			addChild(_button);
		}
		
		protected function setupButtonSkin():void
		{
			if (_selected)
			{
				if (_buttonSelected != null)
				{
					setButton(_buttonSelected);
				}else if(_buttonUp!=null)
				{
					setButton(_buttonUp);
				}else
				{
					_button.upState = _styles[SELECTED_UP_SKIN] as DisplayObject;
					_button.downState = _styles[SELECTED_DOWN_SKIN] as DisplayObject;
					_button.overState = _styles[SELECTED_OVER_SKIN] as DisplayObject;
				}
			}else
			{
				if (_buttonUp != null)
				{
					setButton(_buttonUp);
				}else
				{
					_button.upState = _styles[UP_SKIN] as DisplayObject;
					_button.downState = _styles[DOWN_SKIN] as DisplayObject;
					_button.overState = _styles[OVER_SKIN] as DisplayObject;
				}
			}
		}
		
		protected function setupHitArea():void 
		{
			if ((_button == _buttonSelected) || (_button == _buttonUp))
			{
				return;
			}
			
			if ((_styles[HIT_AREA] as DisplayObject) != null)
			{
				_button.hitTestState = _styles[HIT_AREA] as DisplayObject;
			}else
			{
				_button.hitTestState = _button.upState;
			}
		}
		
		override public function get hitArea():flash.display.Sprite 
		{
			return _styles[HIT_AREA] as Sprite;
		}
		
		override public function set hitArea(value:flash.display.Sprite):void 
		{
			_styles[HIT_AREA] = value;
			invalidate();
		}
		
		
		
		public function get buttonSelected():SimpleButton 
		{
			return _buttonSelected;
		}
		
		public function set buttonSelected(value:SimpleButton):void 
		{
			_buttonSelected = value;
			invalidate();
		}
		
		public function get buttonUp():SimpleButton 
		{
			return _buttonUp;
		}
		
		public function set buttonUp(value:SimpleButton):void 
		{
			_buttonUp = value;
			invalidate();
		}
		
		public function setStyle(styleType:String, styleObject:Object):void
		{
			_styles[styleType] = styleObject;
			invalidate();
		}
		
	}

}